package pw.hais.utils_lib.mina.server

import org.apache.mina.core.service.IoAcceptor
import org.apache.mina.core.session.IdleStatus
import org.apache.mina.core.session.IoSession
import org.apache.mina.filter.codec.ProtocolCodecFilter
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory
import org.apache.mina.filter.keepalive.KeepAliveFilter
import org.apache.mina.filter.logging.LoggingFilter
import org.apache.mina.transport.socket.nio.NioSocketAcceptor
import pw.hais.utils_lib.mina.*
import pw.hais.utils_lib.utils.L
import java.io.IOException
import java.net.InetSocketAddress
import java.util.concurrent.Executors

/**
 * https://github.com/cuihp/AndroidServer
 * Created by cuihp on 2017/4/15.
 */

class MinaServer(val mConfig: SockectConfig, val listener: OnSockectListener) {
    private val mConnectThread = ConnectThread()
    private val mThreadPool = Executors.newFixedThreadPool(1)

    init {
        mThreadPool.execute(mConnectThread)
    }

    fun sendMessage(data: String) {
        L.v("发送消息：$data", "Mina")
        mConnectThread.sendMsg(data)
    }

    private inner class ConnectThread : Runnable {
        internal var acceptor: IoAcceptor? = null
        internal var mSession: IoSession? = null
        override fun run() {
            var acceptor = NioSocketAcceptor()
            acceptor.filterChain.addLast("logger", LoggingFilter())
            acceptor.filterChain.addLast("codec", ProtocolCodecFilter(ObjectSerializationCodecFactory()))

            val kaf = KeepAliveFilter(KeepAliveMessageFactoryImpl(mConfig), IdleStatus.BOTH_IDLE)
            kaf.isForwardEvent = true           //idle事件回发  当session进入idle状态的时候 依然调用handler中的idled方法
            kaf.requestInterval = mConfig.kafiTime  //本服务器为被定型心跳  即需要每10秒接受一个心跳请求  否则该连接进入空闲状态 并且发出idled方法回调
            kaf.requestTimeout = mConfig.kafiTime + 5             //超时时间   如果当前发出一个心跳请求后需要反馈  若反馈超过此事件 默认则关闭连接
            acceptor.filterChain.addLast("heartbeat", kaf)

            acceptor.handler = IoHandler(listener)
            acceptor.sessionConfig.readBufferSize = mConfig.readBufferSize
            //10秒无操作释放Session
            acceptor.sessionConfig.setIdleTime(IdleStatus.BOTH_IDLE, 30)
            try {
                acceptor.bind(InetSocketAddress(mConfig.port))
                L.v("开启监听端口：${mConfig.port}", "MinaServer")
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }

        /**
         * 发送消息
         *
         * @param data
         */
        fun sendMsg(data: String) {
            if (mSession != null && mSession!!.isConnected) {
                mSession!!.write(data)
            }
        }

        /**
         * 断开连接
         */
        fun disConnect() {
            acceptor?.unbind()
        }
    }

    /**
     * 断开连接
     */
    fun disConnect() {
        mConnectThread.disConnect()
    }

}
